- 数组的细节处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int compare(const jint *a, const jint *b) {
return *a - *b;
}
extern "C"
JNIEXPORT void JNICALL
Java_com_zzw_jnidemo_ArrayUtils_sort(JNIEnv *env, jclass type, jintArray array_) {
jint *intArray = env->GetIntArrayElements(array_, NULL);
jsize length = env->GetArrayLength(array_);
//排序
//void *ptr 指向待排序的数组的指针
//size_t count 数组的元素数目
//size_t size 数组每个元素的字节大小
// int (*comp)(const void *, const void *) 比较函数。若首个参数小于第二个,则返回负整数值,若首个参数大于第二个,
// 则返回正整数值,若两参数相等,则返回零。
// void qsort( void *ptr, size_t count, size_t size,int (*comp)(const void *, const void *) );
qsort(intArray, static_cast<size_t>(length), sizeof(int),
reinterpret_cast<int (*)(const void *, const void *)>(compare));
//mode =
//0 表示 既要同步数据给jArray,又要释放intArray
//JNI_COMMIT : copy content, do not free buffer ,会同步数据给jArray,但是不会释放intArray
//JNI_ABORT : free buffer w/o copying back ,不会同步数据给jArray,但是会释放intArray
env->ReleaseIntArrayElements(array_, intArray, JNI_ABORT);
}
2.局部引用和全局引用
1 | //局部变量 |
3.静态缓存策略1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34//局部静态缓存
extern "C"
JNIEXPORT void JNICALL
Java_com_zzw_jnidemo_ArrayUtils_staticLcalCache(JNIEnv *env, jclass type, jstring name_) {
// jfieldID f_id =NULL;
static jfieldID f_id = NULL;//局部缓存 ,这个方法会被多次调用,不需要反复去获取jfieldID
if (!f_id) {
f_id = env->GetStaticFieldID(type, "name", "Ljava/lang/String;");
} else {
LOGE("f_id不为null");//加上static将会缓存
}
env->SetStaticObjectField(type, f_id, name_);
}
//全局静态缓存
static jfieldID jfieldID1;
static jfieldID jfieldID2;
static jfieldID jfieldID3;
//一般初始化的时候调用
extern "C"
JNIEXPORT void JNICALL
Java_com_zzw_jnidemo_ArrayUtils_initStatic(JNIEnv *env, jclass type) {
jfieldID1 = env->GetStaticFieldID(type, "name", "Ljava/lang/String;");
jfieldID2 = env->GetStaticFieldID(type, "name1", "Ljava/lang/String;");
jfieldID3 = env->GetStaticFieldID(type, "name2", "Ljava/lang/String;");
}
//如果反复调用设置值得函数,那么将不会每次都获取id
void setData(JNIEnv *env, jclass jclazz, jobject object) {
env->SetStaticObjectField(jclazz, jfieldID1, object);
env->SetStaticObjectField(jclazz, jfieldID2, object);
env->SetStaticObjectField(jclazz, jfieldID3, object);
}
4.异常处理1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
extern "C"
JNIEXPORT void JNICALL
Java_com_zzw_jnidemo_ArrayUtils_exception2(JNIEnv *env, jclass cls) {
jthrowable exc = NULL;
jmethodID mid = env->GetStaticMethodID(cls, "exceptionCallback", "()V");
if (mid != NULL) {
env->CallStaticVoidMethod(cls, mid);
}
LOGE("In C: Java_com_zzw_jnidemo_ArrayUtils_exception2-->called!!!!");
//这种也是可以检测的
// exc = env->ExceptionOccurred(); // 返回一个指向当前异常对象的引用
// if (exc) {
if (env->ExceptionCheck()) { // 检查JNI调用是否有引发异常
env->ExceptionDescribe();//打印错误信息
env->ExceptionClear(); // 清除引发的异常,在Java层不会打印异常的堆栈信息
env->ThrowNew(env->FindClass("java/lang/Exception"), "JNI抛出的异常!");
return;
}
//补救 。。。
mid = env->GetStaticMethodID(cls, "normalCallback", "()V");
if (mid != NULL) {
env->CallStaticVoidMethod(cls, mid);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
ArrayUtils.exception();
} catch (Exception e) {
e.printStackTrace();//打印抛出的异常
}
}
- c++调用java: 这里需要分为在主线程调用还是在子线程调用,在主线程调用就直接通过函数的
env
调用即可,在子线程调用则需要JavaVM ->AttachCurrentThread
拿到env
然后调用。
1 |
|
JavaListener.h1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class JavaListener {
public:
JavaVM *jvm;
_JNIEnv *jenv;
jobject jobj;
jmethodID jmid;
public:
JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj);
~JavaListener();
/**
* 1:主线程
* 0:子线程
* @param type
* @param code
* @param msg
*/
void onError(int type, int code, const char *msg);
};
JavaListener.cpp1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void JavaListener::onError(int type, int code, const char *msg) {
if(type == 0)
{
JNIEnv *env;
jvm->AttachCurrentThread(&env, 0);
jstring jmsg = env->NewStringUTF(msg);
env->CallVoidMethod(jobj, jmid, code, jmsg);
env->DeleteLocalRef(jmsg);
jvm->DetachCurrentThread();
}
else if(type == 1)
{
jstring jmsg = jenv->NewStringUTF(msg);
jenv->CallVoidMethod(jobj, jmid, code, jmsg);
jenv->DeleteLocalRef(jmsg);
}
}
JavaListener::JavaListener(JavaVM *vm, _JNIEnv *env, jobject obj) {
jvm = vm;
jenv = env;
jobj = obj;
jclass clz = env->GetObjectClass(jobj);
if(!clz)
{
return;
}
jmid = env->GetMethodID(clz, "onError", "(ILjava/lang/String;)V");
if(!jmid)
return;
}
ThreadDemo.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29public class ThreadDemo {
static
{
System.loadLibrary("native-lib");
}
private OnErrerListener onErrerListener;
public void setOnErrerListener(OnErrerListener onErrerListener) {
this.onErrerListener = onErrerListener;
}
public void onError(int code, String msg)
{
if(onErrerListener != null)
{
onErrerListener.onError(code, msg);
}
}
public interface OnErrerListener
{
void onError(int code, String msg);
}
public native void callbackFromC();
}